package pri.hillchen.springbootstd.bms.shiro;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.util.StringUtils;
import pri.hillchen.springbootstd.bms.entity.system.Resource;
import pri.hillchen.springbootstd.bms.entity.system.User;
import pri.hillchen.springbootstd.bms.service.system.ResourceService;
import pri.hillchen.springbootstd.bms.service.system.UserService;

import java.util.List;

/**
 * Created by hillchen on 2017/10/16 0016.
 */
public class ShiroRealm extends AuthorizingRealm {
    @javax.annotation.Resource
    private UserService userService;
    @javax.annotation.Resource
    private ResourceService resourceService;

    /**
     * 身份认证
     * @param authecToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authecToken) throws AuthenticationException {

        UsernamePasswordToken token = (UsernamePasswordToken)authecToken;

        if(StringUtils.isEmpty(token.getUsername())){
            throw new AccountException("用户名不能为空");
        }

        User user = userService.findUserByUserName(token.getUsername());
        if(user == null){
            throw new UnknownAccountException("用户名没找到");
        }else{
            return new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
        }
    }

    /**
     * 权限控制
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        /*
        * 当没有使用缓存的时候，不断刷新页面的话，这个代码会不断执行，
        * 当其实没有必要每次都重新设置权限信息，所以我们需要放到缓存中进行管理；
        * 当放到缓存中时，这样的话，doGetAuthorizationInfo就只会执行一次了，
        * 缓存过期之后会再次执行。
        */
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        User user  = (User)principals.getPrimaryPrincipal();

        List<Resource> resources = resourceService.queryUserVisitableResource(user.getId());
        for(Resource resource : resources){
            authorizationInfo.addStringPermission(resource.getResourceUrl());
        }
        return authorizationInfo;
    }

}
